#include "node_environment/node_environment.h"
#include "proto/internal.pb.h"
#include "Network.h"
#include "OpScan.h"

using namespace internal;

OpScan::OpScan(const ScanOperation &operation) {
	for (int i = 0; i < operation.file_number_size(); ++i) {
		source.push_back(network->openDataSourceFile(operation.file_number(i)));
	}

	for (int i = 0; i < operation.column_size(); i++) {
		switch (operation.type(i)) {
		case ScanOperation_Type_INT:
			output.push_back(Output_elem(malloc(sizeof (int32_t) * TABLESIZE), INT));
			break;
		case ScanOperation_Type_DOUBLE:
			output.push_back(Output_elem(malloc(sizeof (double) *TABLESIZE), DOUBLE));
			break;
		case ScanOperation_Type_BOOL:
			output.push_back(Output_elem(malloc(sizeof (bool) * TABLESIZE), BOOL));
			break;
		default:
			assert(false);
		}
		column_number.push_back(operation.column(i));
	}
}

OpScan::~OpScan() {
	for (int i = 0; i < source.size(); ++i) {
		delete source[i];
	}
}

int OpScan::doit() {
	int ret = 0;

	while (ret == 0 && !source.empty()) {
		for (size_t i = 0; i < output.size(); i++) {
			switch (output[i].type) {
			case INT:
				ret = source.front()->GetInts(column_number[i], TABLESIZE, (int32_t*) output[i].column);
				break;
			case DOUBLE:
				ret = source.front()->GetDoubles(column_number[i], TABLESIZE, (double*) output[i].column);
				break;
			case BOOL:
				ret = source.front()->GetByteBools(column_number[i], TABLESIZE, (bool*) output[i].column);
				break;
			}
		}

		if (ret == 0) {
			source.pop_front();
		} else {
			break;
		}
	}

	return (ret == 0) ? -1 : ret;
}
